package com.example.projectmanagement.service;

import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

@Service
public class FileStorageService {
    
    private final String uploadDir = "uploads/avatars/";
    
    public FileStorageService() {
        // 确保上传目录存在
        File directory = new File(uploadDir);
        if (!directory.exists()) {
            directory.mkdirs();
        }
    }
    
    /**
     * 保存头像文件
     * @param file 上传的文件
     * @param userId 用户ID
     * @return 文件路径
     * @throws IOException
     */
    public String saveAvatar(MultipartFile file, Long userId) throws IOException {
        // 安全检查：验证文件
        validateFile(file);
        
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename);
        
        // 重新生成安全的文件名
        String filename = userId + "_" + UUID.randomUUID().toString() + extension;
        Path filePath = Paths.get(uploadDir, filename);
        
        // 检查文件路径安全性
        validateFilePath(filePath);
        
        // 保存文件
        Files.write(filePath.toAbsolutePath(), file.getBytes());
        
        // 返回相对路径
        return uploadDir + filename;
    }
    
    /**
     * 验证上传的文件安全性
     * @param file 上传的文件
     */
    private void validateFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IOException("文件不能为空");
        }
        
        // 检查文件大小
        long maxSize = 6 * 1024 * 1024; // 6MB
        if (file.getSize() > maxSize) {
            throw new IOException("文件大小超过限制: 6MB，当前文件大小: " + (file.getSize() / 1024 / 1024) + "MB");
        }
        
        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType == null || 
            (!contentType.equals("image/jpeg") && 
             !contentType.equals("image/png") && 
             !contentType.equals("image/jpg"))) {
            throw new IOException("不支持的文件类型: " + contentType);
        }
        
        // 检查文件扩展名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            throw new IOException("文件名不能为空");
        }
        
        String extension = getFileExtension(originalFilename).toLowerCase();
        if (!extension.equals(".jpg") && !extension.equals(".jpeg") && !extension.equals(".png")) {
            throw new IOException("不支持的文件扩展名: " + extension);
        }
        
        // 检查魔术字节（文件头）
        byte[] header = new byte[8];
        InputStream inputStream = file.getInputStream();
        int bytesRead = inputStream.read(header);
        if (bytesRead < 8) {
            throw new IOException("文件太小");
        }
        
        // 检查JPEG文件头
        if (extension.equals(".jpg") || extension.equals(".jpeg")) {
            if (!(header[0] == (byte) 0xFF && header[1] == (byte) 0xD8)) {
                throw new IOException("无效的JPEG文件");
            }
        }
        // 检查PNG文件头
        else if (extension.equals(".png")) {
            if (!(header[0] == (byte) 0x89 && header[1] == (byte) 0x50 && 
                  header[2] == (byte) 0x4E && header[3] == (byte) 0x47 &&
                  header[4] == (byte) 0x0D && header[5] == (byte) 0x0A &&
                  header[6] == (byte) 0x1A && header[7] == (byte) 0x0A)) {
                throw new IOException("无效的PNG文件");
            }
        }
    }
    
    /**
     * 获取文件扩展名
     * @param filename 文件名
     * @return 扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.lastIndexOf('.') == -1) {
            return "";
        }
        return filename.substring(filename.lastIndexOf('.'));
    }
    
    /**
     * 验证文件路径安全性
     * @param filePath 文件路径
     */
    private void validateFilePath(Path filePath) throws IOException {
        // 解析路径以防止路径遍历攻击
        Path absoluteFilePath = filePath.toAbsolutePath();
        Path normalizedPath = absoluteFilePath.normalize();
        Path uploadDirPath = Paths.get(uploadDir).toAbsolutePath().normalize();
        
        // 确保文件路径在上传目录内
        if (!normalizedPath.startsWith(uploadDirPath)) {
            throw new IOException("不安全的文件路径: 文件必须在上传目录内");
        }
        
        // 检查路径深度
        if (normalizedPath.getNameCount() > uploadDirPath.getNameCount() + 2) {
            throw new IOException("文件路径过深");
        }
        
        // 检查文件名是否包含非法字符
        String fileName = normalizedPath.getFileName().toString();
        if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
            throw new IOException("文件名包含非法字符");
        }
    }
    
    /**
     * 删除头像文件
     * @param filePath 文件路径
     * @throws IOException
     */
    public void deleteAvatar(String filePath) throws IOException {
        if (filePath != null && !filePath.isEmpty()) {
            // 验证文件路径安全性
            Path path = Paths.get(filePath);
            validateFilePath(path);
            
            Path absolutePath = path.toAbsolutePath();
            if (Files.exists(absolutePath) && Files.isRegularFile(absolutePath)) {
                Files.delete(absolutePath);
            }
        }
    }
}